<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
    <script>
        const data = {
            name:'atguigu',
            age:20,
            address:{
                city:'北京'
            },
            a:{
                b:{
                    c:{
                        d:{
                            e:111
                        }
                    }
                }
            },
            arr:[1,2,3]
        }

        //重新创建一个数组的原型，让该原型对象的隐式原型链__proto__ 指向 数组的原型对象
        // const 新对象 = Object.create(老对象) ，新对象的隐式原型指向老对象

        const oldPrototype = Array.prototype
        const newPrototype = Object.create(oldPrototype)
        // 在新的原型对象上新增数组的 7 个方法
        const methods = ['push', 'pop', 'unshift', 'shift', 'reverse', 'splice', 'sort']
        methods.forEach(method=>{
            newPrototype[method] = function(){
                // 1. 调用原数组方法
                oldPrototype[method].apply(this, arguments)
                // 2. 通知视图更新
                updateView()
            }
        })
        console.log('newPrototype: ', newPrototype)


        // 通知视图更新
        function updateView(){
            console.log('视图更新')
        }

        // 添加响应式
        function defineActive(target, key, value){
            // 递归调用深度监听
            observer(value)
            Object.defineProperty(target, key, {
                get(){
                    return value
                },
                // 数据变化的时候触发
                set(newValue){
                    if(value !== newValue){
                        observer(newValue)
                        value = newValue
                        updateView()
                    }
                }
            })
        }

        /**
         * target: object function array string number  boolean
         * 
         */
        function observer(target){ 
            if(typeof target !== 'object' && target !== null){ // 基本数据类型
                return target
            }
            // 说明他是数组或者是对象
            // 1. 如果是数组
            if(Array.isArray(target)){
                target.__proto__ = newPrototype
            }
            // 2. 如果是对象
            for(let key in target){
                defineActive(target, key, target[key])
            }
        }


        observer(data)

        // console.log(data)

        // data.name = '尚硅谷'
        // console.log('name:',data.name)

        // data.age = {realAge:80, openAge:19}

        // data.sex = '女'  //Vue.set(data,'sex','女')
        
        data.arr.push(123)
        
    </script>
</body>
</html>